package org.devops
class K8sDeployer {
    // 动态获取集群凭证
    def getClusterCredential(String envType) {
        def credentials = [
            'prod': 'k8s-prod-config',
            'test': 'k8s-test-config'
        ]
        return credentials[envType]
    }
    // 部署应用到 Kubernetes
    def Deploy(script, String envType,String controllerType, String imageName, String fullImage, String namespace) {
        def clusterCredential = getClusterCredential(envType)
        def resourceFile = "${controllerType}.yaml"
        script.withCredentials([script.file(credentialsId: clusterCredential, variable: 'KUBECONFIG')]) {
            
            script.container('kubectl') {
                try {
                    // 动态路径
                    String resourceFilePath = "${script.env.WORKSPACE}"
                    String svcPath = "${script.env.WORKSPACE}/svc.yaml"
                    script.sh """
                        ls -l "${resourceFilePath}" || exit 1
                        ls -l "${svcPath}" || exit 1
                        kubectl apply -f ${resourceFile} -n ${namespace} && \\
                        kubectl apply -f ${svcPath} -n ${namespace} && \\
                        ${getRolloutCommand(controllerType, imageName, namespace)}
                    """
                    script.echo "✅ 已部署 ${fullImage} 到 ${namespace}"
                } catch (Exception e) {
                    script.error "🚨 部署失败: ${e.message}"
                }
            }
        }
    }
    // 添加Helm部署方法
    def HelmDeploy(script, String envType, String releaseName, String chartNameOrPath, 
                String namespace, Map values = [:],String chartVersion = "") {    
        def clusterCredential = getClusterCredential(envType)
        script.withCredentials([script.file(credentialsId: clusterCredential, variable: 'KUBECONFIG')]) {
            script.container('helm') {
                try {
                    // 转换values为helm格式
                    def valueArgs = values.collect { k, v -> "--set ${k}=${v}" }.join(' ')
                    // 判断Chart来源是仓库还是本地路径
                    def isRepoChart = chartNameOrPath.contains('/')  // 简单判断是否为repo/name格式
                    def chartRef = chartNameOrPath
                    if (isRepoChart) {
                        // 添加Harbor仓库并更新索引（示例URL，需替换为实际仓库地址）
                        // script.sh """
                        //     helm repo add --ca-file /usr/local/harbor.jdicity.local.crt   --key-file /usr/local/harobor.jdicity.local.key ${releaseName}  https://harbor.jdicity.local/chartrepo/myrepo
                        // """
                        script.sh """
                            helm repo update  ${releaseName}
                        """
                        // 拼接版本参数
                        if (chartVersion) {
                            chartRef += " --version ${chartVersion}"
                        }
                    } else {
                        // 本地Chart路径检查
                        script.echo "🔍 检查本地Chart文件: ${chartNameOrPath}"
                        def chartFiles = script.sh(script: "ls -l ${chartNameOrPath} 2>/dev/null || echo ''", returnStdout: true).trim()
                        if (chartFiles.size() == 0) {
                            script.error "🚨 Helm Chart文件未找到: ${chartNameOrPath}"
                        }
                    }
                    script.echo "🚀 开始Helm部署..."
                    def deployCmd = """
                        helm upgrade --install ${releaseName} ${chartRef} \
                            --namespace ${namespace} \
                            ${valueArgs} \
                            --atomic --wait \
                            --debug \
                            --timeout 5m0s
                    """
                    script.sh(deployCmd)
                    
                    // 验证部署状态
                    def status = script.sh(script: "helm status ${releaseName} -n ${namespace}", returnStdout: true)
                    script.echo "🔍 部署状态:\n${status}"
                } catch (Exception e) {
                    script.error "🚨 Helm部署失败: ${e.message}"
                }
            }
        }
    }
    // 获取状态检查命令
    private String getRolloutCommand(String controllerType, String imageName, String namespace) {
        if (controllerType == 'statefulset') {
            return "kubectl rollout status statefulset/${imageName} -n ${namespace} --timeout=120s"
        }
        return "kubectl rollout status deployment/${imageName} -n ${namespace} --timeout=120s"
    }

    // 新增函数：获取Deployment的可用修订版本号
    def getRollbackVersions(script, controllerType,controllerName, namespace) {
        // 获取kubectl rollout history输出
        def history = script.sh(
            script: "kubectl rollout history ${controllerType}/${controllerName} -n ${namespace}",
            returnStdout: true
        ).trim()
        
        // 解析REVISION号 (示例输出见下方说明)
        def versions = []
        history.split('\n').each { line ->
            if (line =~ /^[0-9]+\s+/) { // 匹配以数字开头的行
                def parts = line.split(/\s+/, 3)
                def revision = parts[0]
                // 获取该版本对应的镜像
                def image = getImageForRevision(script, controllerType, controllerName, revision, namespace)
                // 格式化为"revision - image"的显示格式
                versions.add("${revision} - ${image}")
            }
        }
        return versions.reverse() // 按从新到旧排序
    }
    // 获取镜像地址
    def getImageForRevision(script, controllerType, controllerName, revision, namespace) {
        def imageName = script.sh(
            script: "kubectl rollout history ${controllerType}/${controllerName} -n ${namespace} --revision=${revision} -o=json | jq -r '.spec.template.spec.containers[0].image'",
            returnStdout: true
        ).trim()
        return imageName
    }
    // 快速回滚应用
    def Rollback(script, String envType, String controllerType,  String imageName, String namespace , Integer timeoutMinutes = 60) {
        def clusterCredential = getClusterCredential(envType)
        script.withCredentials([script.file(credentialsId: clusterCredential, variable: 'KUBECONFIG')]) {
            script.container('kubectl') {
                script.timeout(time: timeoutMinutes, unit: 'MINUTES') {
                    try {
                        
                        // 在 Rollback 方法中调用
                        def versions = getRollbackVersions(script, controllerType,imageName, namespace)
                        if (versions.isEmpty()) {
                            script.error "没有可用的回滚版本！"
                            return
                        }
                        def userChoice = script.input(
                            message: "选择要回滚的版本",
                            parameters: [
                                [
                                    $class: 'ChoiceParameterDefinition',
                                    name: 'VERSION',
                                    choices: versions.join('\n'),
                                    description: '可用历史版本'
                                ]
                            ]
                        )
                        // 提取版本号
                        def revision = userChoice.split('-')[0].trim()
                        if (!revision.isInteger()) {
                            script.error "无效的版本格式: ${userChoice}"
                        }
                        // 执行回滚
                        script.sh """
                            kubectl rollout undo ${controllerType}/${imageName} -n ${namespace} --to-revision=${revision} && \
                            ${getRolloutCommand(controllerType, imageName, namespace)}
                        """
                        // 获取该版本对应的镜像地址
                        def rollbackImage = userChoice.split('-', 2)[1].trim()
                        script.echo "✅ 已回滚 ${imageName} 到版本 ${revision} (镜像: ${rollbackImage})"
                        // 传递回滚后的镜像地址
                        return rollbackImage
                    } catch (Exception e) {
                        script.error "🚨 回滚过程异常: ${e.getMessage()}"
                    }
                }
            }
        }
    }
    // Helm回滚方法
    def HelmRollback(script, String envType, String releaseName, String namespace,String imageName) {
        def clusterCredential = getClusterCredential(envType)
        script.withCredentials([script.file(credentialsId: clusterCredential, variable: 'KUBECONFIG')]) {
            script.container('helm') {
                try {
                    // 获取历史版本列表
                    def history = script.sh(
                        script: "helm history ${releaseName} -n ${namespace}",
                        returnStdout: true
                    ).trim()
                    
                    // 解析版本号并获取每个版本的镜像
                    def images = []
                    history.split('\n').each { line ->
                        if (line =~ /^[0-9]+\s+/) {
                            def revision = line.split(/\s+/)[0]
                            def image = script.sh(
                                script: "helm get values ${releaseName} -n ${namespace} --revision=${revision} -o json | jq -r '.image.repository'",
                                returnStdout: true
                            ).trim()
                            if (image && image != "null") {
                                images << image
                            }
                        }
                    }
                    
                    // 去重并排序
                    images = images.unique().sort()
                    
                    if (images.size() == 0) {
                        script.error "没有可用的镜像版本！"
                        return
                    }
                    
                    // 让用户选择要回滚的镜像
                    def userChoice = script.input(
                        message: "选择要回滚的镜像版本",
                        parameters: [
                            [
                                $class: 'ChoiceParameterDefinition',
                                name: 'IMAGE_VERSION',
                                choices: images.join('\n'),
                                description: '可用镜像版本'
                            ]
                        ]
                    )
                    // script.sh """
                    //     helm repo remove ${releaseName} || true
                    // """
                    // script.sh """
                    //     helm repo add ${releaseName} https://harbor.jdicity.local/chartrepo/myrepo --ca-file /usr/local/harbor.jdicity.local.crt \
                    //         --username ${HARBOR_USER} \
                    //         --password '${HARBOR_PASSWORD.replace("'", "'\\''")}'
                    // """
                    script.sh """
                        helm repo update  ${releaseName}
                    """
                    // 执行回滚到指定镜像
                    script.sh """
                        helm upgrade ${releaseName} ${releaseName}/${imageName} \
                            --namespace ${namespace} \
                            --reuse-values \
                            --set image.repository=${userChoice} \
                            --atomic --wait \
                            --debug \
                            --timeout 5m0s
                    """
                    
                    script.echo "✅ 已回滚 ${releaseName} 到镜像版本: ${userChoice}"
                    return userChoice
                    
                } catch (Exception e) {
                    script.error "🚨 Helm回滚失败: ${e.message}"
                    // throw e
                }
            }
        }
    }
}